#!/usr/bin/env node

const { exec } = require('child_process');
const { readFileSync, writeFileSync } = require('fs');
const { transpile } = require('../ts2c');

runTest(process.argv[2]).then(result => {
    console.log(result);
    process.exit(0);
});


async function runTest(testFile) {
    const testFileContents = readFileSync(testFile, "utf8")
        .replace(/\$ERROR\(/g, "console.log(")
        .replace(/\$FAIL\(/g, "console.log(")
        .replace(/eval\(("[^\n\r]+")\)/g, (m, m1) => eval(m1));
    const isNegative = testFileContents.indexOf("@negative") > -1;
    const { ERROR, PASS } = isNegative ? { ERROR: "PASS: (negative)", PASS: "ERROR: (negative)" } : { ERROR: "ERROR:", PASS: "PASS:" };

    const testFile_c = testFile.replace(/\.js$/, ".c");
    const log = console.log;
    console.log = () => {};
    try {
        const cCode = transpile(testFileContents);
        writeFileSync(testFile_c, cCode);
        console.log = log;
    } catch(e) {
        console.log = log;
        return `${ERROR} cannot transpile ${testFile}`;
    }
    
    const testFile_elf = testFile.replace(/\.js$/, ".elf");
    let res = await execAsync(`gcc ${testFile_c} -ansi -pedantic -Wall -g -o ${testFile_elf}`);
    if (res.err)
        return `${ERROR} cannot compile ${testFile_c}`;

    res = await execAsync(`${testFile_elf.indexOf('/') === 0 ? testFile_elf : "./" + testFile_elf}`);
    if (res.err)
        return `${ERROR} cannot execute ${testFile_elf}`;
    if (res.stdout)
        return `${ERROR} ${res.stdout.split('\n').length} errors found when validating ${testFile}`;

    return `${PASS} ${testFile}`;
}

async function execAsync(cmd) {
    return new Promise(resolve => exec(cmd, (err, stdout, stderr) => {
        resolve({ err, stdout, stderr });
    }));
}
